unit uCap;

interface

  uses
    Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
    Dialogs, jpeg, StdCtrls;

  type
    CAPDRIVERCAPS=record
      wDeviceIndex:cardinal;
      fHasOverlay,
      fHasDlgVideoSource,
      fHasDlgVideoFormat,
      fHasDlgVideoDisplay,
      fCaptureInitialized,
      fDriverSuppliesPalettes:longbool;
      hVideoIn,
      hVideoOut,
      hVideoExtIn,
      hVideoExtOut:Cardinal;
  end;
  pCAPDRIVERCAPS=^CAPDRIVERCAPS;

  type
    CAPSTATUS=record
      uiImageWidth,
      uiImageHeight:cardinal;
      fLiveWindow,
      fOverlayWindow,
      fScale:longbool;
      ptScroll:TPoint;
      fUsingDefaultPalette,
      fAudioHardware,
      fCapFileExists:longbool;
      dwCurrentVideoFrame,
      dwCurrentVideoFramesDropped,
      dwCurrentWaveSamples,
      dwCurrentTimeElapsedMS,
      hPalCurrent:cardinal;
      fCapturingNow:longbool;
      dwReturn,
      wNumVideoAllocated,
      wNumAudioAllocated:cardinal;
  end;
  pCAPSTATUS=^CAPSTATUS;

  type
    WAVEFORMATEX=record
      wFormatTag,
      nChannels:word;
      nSamplesPerSec,
      nAvgBytesPerSec:cardinal;
      nBlockAlign,
      wBitsPerSample,
      cbSize:dword;
  end;
  pWAVEFORMATEX=^WAVEFORMATEX;

  type
    CAPINFOCHUNK=record
      fccInfoID:cardinal;
      lpData:pointer;
      cbDataLen:cardinal;
  end;
  pCAPINFOCHUNK=^CAPINFOCHUNK;

  type
    CAPTUREPARMS=record
      dwRequestMicroSecPerFrame:cardinal;
      fMakeUserHitOKToCapture:longbool;
      wPercentDropForError:cardinal;
      fYield:longbool;
      dwIndexSize,
      wChunkGranularity:cardinal;
      fUsingDOSMemory:longbool;
      wNumVideoRequested:cardinal;
      fCaptureAudio:longbool;
      wNumAudioRequested,
      vKeyAbort:cardinal;
      fAbortLeftMouse,
      fAbortRightMouse,
      fLimitEnabled:longbool;
      wTimeLimit:cardinal;
      fMCIControl,
      fStepMCIDevice:longbool;
      dwMCIStartTime,
      dwMCIStopTime:cardinal;
      fStepCaptureAt2x:longbool;
      wStepCaptureAverageFrames:cardinal;
      dwAudioBufferSize:cardinal;
      fDisableWriteCache:longbool;
      AVStreamMaster:cardinal;
  end;
  pCAPTUREPARMS=^CAPTUREPARMS;

  type
    VIDEOHDR=record
      lpData:pointer;
      dwBufferLength,
      dwBytesUsed,
      dwTimeCaptured,
      dwUser,
      dwFlags:cardinal;
      dwReserved:array [0..3] of cardinal;
  end;
  pVIDEOHDR=^VIDEOHDR;

  const VHDR_DONE = 1;
  const VHDR_PREPARED = 2;
  const VHDR_INQUEUE = 4;
  const VHDR_KEYFRAME = 8;

  function VideoStreamCallback(hWnd:cardinal; vHeader:pVIDEOHDR):cardinal; stdcall;
  function FrameCallback(hWnd:cardinal; vHeader:pVIDEOHDR):cardinal; stdcall;
  function CapControlCallback (hWnd,nState:cardinal):Cardinal; stdcall;
  function ErrorCallBack (hWnd,nId:Cardinal; nDescription:pansichar):cardinal; stdcall;
  function StatusCallBack (hWnd,nId:Cardinal; nDescription:pansichar):cardinal; stdcall;

  function capCreateCaptureWindowA(windowName:PAnsiChar; dwstyle, x, y, cx, cy, parentHwnd,nId:cardinal):cardinal; stdcall; external 'avicap32.dll';
  function capGetDriverDescriptionA(drvIndex:cardinal; Name:PAnsiChar; NameLen:cardinal; Description:PAnsiChar;DescLen:cardinal):cardinal; stdcall; external 'avicap32.dll';

  const WM_CAP_START = WM_USER ;

  const WM_CAP_GET_CAPSTREAMPTR  =         (WM_CAP_START+  1) ;

  const WM_CAP_SET_CALLBACK_ERRORA  =      (WM_CAP_START+  2) ;
  const WM_CAP_SET_CALLBACK_STATUSA  =     (WM_CAP_START+  3) ;

  const WM_CAP_SET_CALLBACK_YIELD =        (WM_CAP_START+  4) ;
  const WM_CAP_SET_CALLBACK_FRAME =        (WM_CAP_START+  5) ;
  const WM_CAP_SET_CALLBACK_VIDEOSTREAM  = (WM_CAP_START+  6) ;
  const WM_CAP_SET_CALLBACK_WAVESTREAM =   (WM_CAP_START+  7) ;
  const WM_CAP_GET_USER_DATA =          (WM_CAP_START+  8) ;
  const WM_CAP_SET_USER_DATA =          (WM_CAP_START+  9) ;

  const WM_CAP_FILE_ALLOCATE =             (WM_CAP_START+  22);
  const WM_CAP_FILE_SET_INFOCHUNK =        (WM_CAP_START+  24);

  const WM_CAP_DRIVER_CONNECT =            (WM_CAP_START+  10);
  const WM_CAP_DRIVER_DISCONNECT=          (WM_CAP_START+  11);
  const WM_CAP_DRIVER_GET_NAMEA=           (WM_CAP_START+  12);
  const WM_CAP_DRIVER_GET_VERSIONA =       (WM_CAP_START+  13);
  const WM_CAP_DRIVER_GET_CAPS=            (WM_CAP_START+  14);

  const WM_CAP_FILE_SET_CAPTURE_FILEA =    (WM_CAP_START+  20);
  const WM_CAP_FILE_GET_CAPTURE_FILEA=     (WM_CAP_START+  21);
  const WM_CAP_FILE_SAVEASA =              (WM_CAP_START+  23) ;
  const WM_CAP_FILE_SAVEDIBA =             (WM_CAP_START+  25) ;

  const WM_CAP_EDIT_COPY =                 (WM_CAP_START+  30) ;
  const WM_CAP_SET_AUDIOFORMAT =           (WM_CAP_START+  35) ;
  const WM_CAP_GET_AUDIOFORMAT =           (WM_CAP_START+  36) ;

  const WM_CAP_GET_VIDEOFORMAT  =          (WM_CAP_START+  44) ;
  const WM_CAP_SET_VIDEOFORMAT  =          (WM_CAP_START+  45) ;

  const WM_CAP_DLG_VIDEOFORMAT=            (WM_CAP_START+  41);
  const WM_CAP_DLG_VIDEOSOURCE=            (WM_CAP_START+  42);
  const WM_CAP_DLG_VIDEODISPLAY=           (WM_CAP_START+  43);
  const WM_CAP_DLG_VIDEOCOMPRESSION =      (WM_CAP_START+  46) ;

  const WM_CAP_SET_PREVIEW=                (WM_CAP_START+  50);
  const WM_CAP_SET_OVERLAY=                (WM_CAP_START+  51);
  const WM_CAP_SET_PREVIEWRATE =           (WM_CAP_START+  52);
  const WM_CAP_SET_SCALE =                 (WM_CAP_START+  53);
  const WM_CAP_GET_STATUS =                (WM_CAP_START+  54);
  const WM_CAP_SET_SCROLL  =               (WM_CAP_START+  55) ;

  const WM_CAP_GRAB_FRAME =                (WM_CAP_START+  60);
  const WM_CAP_GRAB_FRAME_NOSTOP =         (WM_CAP_START+  61) ;

  const WM_CAP_SEQUENCE  =                 (WM_CAP_START+  62) ;
  const WM_CAP_SEQUENCE_NOFILE =           (WM_CAP_START+  63) ;
  const WM_CAP_SET_SEQUENCE_SETUP =        (WM_CAP_START+  64) ;
  const WM_CAP_GET_SEQUENCE_SETUP =        (WM_CAP_START+  65) ;

  const WM_CAP_STOP =                      (WM_CAP_START+  68)  ;
  const WM_CAP_ABORT =                     (WM_CAP_START+  69)  ;

  const WM_CAP_SET_MCI_DEVICEA =           (WM_CAP_START+  66);
  const WM_CAP_GET_MCI_DEVICEA =           (WM_CAP_START+  67);

  const WM_CAP_SINGLE_FRAME_OPEN =         (WM_CAP_START+  70) ;
  const WM_CAP_SINGLE_FRAME_CLOSE =        (WM_CAP_START+  71) ;
  const WM_CAP_SINGLE_FRAME  =             (WM_CAP_START+  72) ;

  const WM_CAP_PAL_OPENA  =                (WM_CAP_START+  80) ;
  const WM_CAP_PAL_SAVEA  =                (WM_CAP_START+  81);
  const WM_CAP_PAL_PASTE  =                (WM_CAP_START+  82) ;
  const WM_CAP_PAL_AUTOCREATE =            (WM_CAP_START+  83) ;
  const WM_CAP_PAL_MANUALCREATE  =         (WM_CAP_START+  84) ;
  const WM_CAP_SET_CALLBACK_CAPCONTROL =   (WM_CAP_START+  85) ;

  type
    TCapturedStringList=array [0..9] of string;

  type
    TCapture=class;

    Callback_Video=procedure (AOwner:TCapture; vHeader:pVIDEOHDR) of object;
    Callback_Control=function (AOwner:TCapture; nState:cardinal):longbool of object;
    Callback_Error_Status=procedure (AOwner:TCapture; nId:Cardinal; nDescription:pansichar) of object;

    TCapture=class

  private
    wParentW:cardinal;
    wX,wY,wCX,wCY:cardinal;
    wStyle:cardinal;
    wName:string;
    wHandle:cardinal;
    wRate:cardinal;
    wPrev:longbool;
    wIdx:cardinal;
    wScale:longbool;
    wOverlay:longbool;
    wAlloc:cardinal;
    wSingleFrm:longbool;

    cbVideoStream:Callback_Video;
    cbFrame:Callback_Video;
    cbCapCtrl:Callback_Control;
    cbError:Callback_Error_Status;
    cbStatus:Callback_Error_Status;

  protected
    procedure SetPreview (sPrev:longbool);
    procedure SetScale (sScale:longbool);
    procedure SetOverlay (sOverlay:longbool);
    procedure SetName (const sName:string);
    procedure SetCapFile (const sName:string);
    function GetCapFile:string;
    procedure SetX (X:cardinal);
    procedure SetY (Y:cardinal);
    procedure SetCX (CX:cardinal);
    procedure SetCY (CY:cardinal);
    procedure BoundWindow;
    procedure SetAllocFile(sLen:cardinal);
    procedure SetSingleFrame(sFrame:longbool);
    function GetInit:longbool;

  public
    function CreateCaptureWindow(ParentHandle:cardinal):longbool;
    procedure Show;
    function Connect(index:cardinal):longbool;
    function Disconnect:longbool;

    function SetCaptureFileInfoChunk (const infoChunk:CAPINFOCHUNK):longbool;
    function SetPreviewRate(FrameRate:cardinal):longbool;
    procedure Scroll (X,Y:cardinal); stdcall;

    property Preview:longbool read wPrev write SetPreview;
    property Scale:longbool read wScale write SetScale;
    property Overlay:longbool read wOverlay write SetOverlay;
    property SingleFrameCapture:longbool read wSingleFrm write SetSingleFrame;
    property CaptureFilename:string read GetCapFile write SetCapFile;
    property PreallocateCaptureFile:cardinal read wAlloc write SetAllocFile;
    property Initialized:longbool read GetInit;
    procedure VideoSourceDialog;
    procedure VideoDisplayDialog;
    procedure VideoFormatDialog;

    function VideoBufferToClipboard:longbool;

    function FrameToBitmapFile (const fileName:string):longbool;
    function FrameToJpgFile(const fileName: string; const bmpName: string; jpgCompression: integer): longbool;
    function FrameStill:longbool;
    function CaptureStartSingleFrame:longbool;

    class function GetIndexedCaptureDrivers (var names, descriptions:TCapturedStringList):longbool;

    function GetCurrentCaptureDriver (var DriverName,DriverDescription:string) :longbool;
    function GetCurrentIndexedDeviceCapabilities(var DevCap:CAPDRIVERCAPS):longbool;
    function GetStatus (var cap:CAPSTATUS):longbool;
    function GetVideoFormat (var bmpInfo:BITMAPINFO):longbool;
    function SetVideoFormat (const bmpInfo:BITMAPINFO):longbool;
    function GetCaptureSettings (var captureSettings:CAPTUREPARMS):longbool;
    function SetCaptureSettings (const captureSettings:CAPTUREPARMS):longbool;

    destructor Destroy;

    procedure SetWindowBound(X,Y,Width,Height:cardinal);

    property X:cardinal read wX write SetX;
    property Y:cardinal read wY write SetY;
    property Width:cardinal read wCX write SetCx;
    property Height:cardinal read wCY write SetCy;
    property Handle:cardinal read wHandle;
    property WindowName:string read wName write SetName;

    property CallBackVideoStream:Callback_Video write cbVideoStream;
    property CallBackFrame:Callback_Video write cbFrame;
    property CallBackCaptureControl:Callback_Control write cbCapCtrl;
    property CallBackError:Callback_Error_Status write cbError;
    property CallBackStatus:Callback_Error_Status write cbStatus;
end;

implementation

{ TCapture }
function TCapture.Connect(index:cardinal): longbool;
begin
  result := longbool(SendMessage (wHandle, WM_CAP_DRIVER_CONNECT, index, 0));
  if result then
    wIdx := index;
end;

function TCapture.Disconnect: longbool;
begin
  result := longbool(SendMessage (wHandle, WM_CAP_DRIVER_DISCONNECT, wIdx, 0));
end;

function TCapture.SetPreviewRate(frameRate:cardinal):longbool;
begin
  result := longbool(SendMessage (wHandle, WM_CAP_SET_PREVIEWRATE, frameRate, 0));
  if result then
    wRate := frameRate;
end;

function TCapture.CreateCaptureWindow(ParentHandle:cardinal):longbool;
begin
  if wHandle = 0 then
  begin
    wParentW := ParentHandle;
    if wParentW <> 0 then
      wStyle := wStyle or WS_CHILD;

    wHandle := capCreateCaptureWindowA(pointer(wName), wStyle, wX, wY, wCx, wCy, wParentW, 0);
    result := longbool(wHandle);
    if result then
    begin
      SetProp(WHandle, 'OwnerObject',Integer(Pointer(self)));
      SendMessage (wHandle, WM_CAP_SET_CALLBACK_VIDEOSTREAM, 0, Integer(Addr(VideoStreamCallback)));
      SendMessage (wHandle, WM_CAP_SET_CALLBACK_FRAME, 0, Integer(Addr(FrameCallback)));
      SendMessage (wHandle, WM_CAP_SET_CALLBACK_CAPCONTROL, 0, Integer(Addr(CapControlCallback)));
      SendMessage (wHandle, WM_CAP_SET_CALLBACK_ERRORA, 0, Integer(Addr(ErrorCallback)));
      SendMessage (wHandle, WM_CAP_SET_CALLBACK_STATUSA, 0, Integer(Addr(StatusCallback)));
    end;
  end;
end;

destructor TCapture.Destroy;
begin
  if wHandle <> 0 then
  begin
    Disconnect;
    RemoveProp(wHandle, 'OwnerObject');
    DestroyWindow(wHandle);
    wHandle := 0;
  end;
end;

procedure TCapture.Show;
begin
  ShowWindow(wHandle, 1);
end;

class function TCapture.GetIndexedCaptureDrivers(var names, descriptions: TCapturedStringList): longbool;
var
  x    :cardinal;
  lLen :cardinal;
begin
  for x := 0 to 9 do
  begin
    setLength(names[x],256);
    setLength(descriptions[x],256);
    capGetDriverDescriptionA(x, Pointer(names[x]), 256, Pointer(descriptions[x]), 256);

    lLen := LStrLen(Pointer(names[x]));
    setLength(names[x], lLen);

    lLen := LStrLen(Pointer(descriptions[x]));
    setLength(descriptions[x], lLen);
  end;
end;

function TCapture.GetCurrentCaptureDriver (var driverName, driverDescription:string) :longbool;
var
  lLen :cardinal;
begin
  result := false;
  SetLength(driverName, 256);
  SetLength(driverDescription, 256);

  if SendMessage(wHandle, WM_CAP_DRIVER_GET_NAMEA, 256, Integer(Pointer(result))) = 0 then exit;
  lLen := LStrLen(Pointer(driverName));
  setLength(driverName, lLen);

  SendMessage(wHandle, WM_CAP_DRIVER_GET_VERSIONA, 256, Integer(Pointer(driverDescription)));
  lLen := LStrLen(Pointer(driverDescription));
  setLength(driverDescription, lLen);

  result := true;
end;

procedure TCapture.VideoSourceDialog;
begin
  SendMessage(wHandle, WM_CAP_DLG_VIDEOSOURCE, 0, 0);
end;

procedure TCapture.VideoDisplayDialog;
begin
  SendMessage(wHandle, WM_CAP_DLG_VIDEODISPLAY, 0, 0);
end;

procedure TCapture.VideoFormatDialog;
begin
  SendMessage(wHandle, WM_CAP_DLG_VIDEOFORMAT, 0, 0);
end;

function TCapture.GetCurrentIndexedDeviceCapabilities(var devCap:CAPDRIVERCAPS): longbool;
begin
  result := LongBool(SendMessage(wHandle, WM_CAP_DRIVER_GET_CAPS, SizeOf(CAPDRIVERCAPS), Integer(Addr(devCap))));
end;

procedure TCapture.SetPreview(sPrev: longbool);
begin
  wPrev := sPrev;
  SendMessage(wHandle, WM_CAP_SET_PREVIEW, Integer(sPrev), 0);
end;

procedure TCapture.SetScale(sScale: longbool);
begin
  wScale := sScale;
  SendMessage(wHandle, WM_CAP_SET_SCALE, Integer(sScale), 0);
end;

procedure TCapture.SetOverlay(sOverlay: longbool);
begin
  wOverlay := sOverlay;
  SendMessage(wHandle, WM_CAP_SET_OVERLAY, Integer(sOverlay), 0);
end;

procedure TCapture.SetName(const sName: string);
begin
  wName := sName;
  if wHandle <> 0 then
    SetWindowText(wHandle,Pointer(sName));
end;

procedure TCapture.SetCapFile(const sName: string);
begin
  SendMessage(wHandle, WM_CAP_FILE_SET_CAPTURE_FILEA, 0, Integer(Pointer(sName)));
end;

function  TCapture.GetCapFile:string;
var
  lLen :cardinal;
begin
  SetLength(result, 1024);
  SendMessage(wHandle, WM_CAP_FILE_GET_CAPTURE_FILEA, 1024, Integer(Pointer(result)));
  lLen := LStrLen(Pointer(result));
  SetLength(result,llen);
end;

procedure TCapture.SetCX(CX: cardinal);
begin
  wCX := CX;
  BoundWindow;
end;

procedure TCapture.SetCY(CY: cardinal);
begin
  wCY := CY;
  BoundWindow;
end;

procedure TCapture.SetX(X: cardinal);
begin
  wX := X;
  BoundWindow;
end;

procedure TCapture.SetY(Y: cardinal);
begin
  wY := Y;
  BoundWindow;
end;

procedure TCapture.BoundWindow;
begin
  SetWindowPos(wHandle, 0, wX, wY, wCx, wCy, SWP_NOACTIVATE or SWP_NOOWNERZORDER or SWP_NOZORDER);
end;

procedure TCapture.SetWindowBound(X, Y, Width, Height: cardinal);
begin
  wX  := x;
  wY  := y;
  wCx := Width;
  wCy := Height;
  BoundWindow;
end;

procedure TCapture.SetAllocFile(sLen: cardinal);
begin
  if SendMessage(wHandle, WM_CAP_FILE_ALLOCATE, 0, sLen) <> 0 then wAlloc := sLen;
end;

function TCapture.GetStatus(var cap: CAPSTATUS): longbool;
begin
  result := LongBool(SendMessage(wHandle, WM_CAP_GET_STATUS, SizeOf(CAPSTATUS), Integer(Addr(cap))));
end;

function TCapture.GetVideoFormat(var bmpInfo: BITMAPINFO): longbool;
begin
  result := LongBool(SendMessage (wHandle,WM_CAP_GET_VIDEOFORMAT, SizeOf(BITMAPINFO), Integer(Addr(bmpInfo))));
end;

function TCapture.SetVideoFormat(const bmpInfo: BITMAPINFO): longbool;
begin
  result := LongBool(SendMessage(wHandle, WM_CAP_SET_VIDEOFORMAT, SizeOf(BITMAPINFO), Integer(Addr(bmpInfo))));
end;

procedure TCapture.Scroll(X,Y:cardinal);
begin
  SendMessage(wHandle, WM_CAP_SET_SCROLL, 0, Integer(Addr(X)));
end;

function TCapture.SetCaptureFileInfoChunk(const infoChunk: CAPINFOCHUNK):longbool;
begin
  result := LongBool(SendMessage(wHandle, WM_CAP_FILE_SET_INFOCHUNK, 0, Integer(Addr(infoChunk))));
end;

function TCapture.GetCaptureSettings(var captureSettings: CAPTUREPARMS): longbool;
begin
  result := LongBool(SendMessage(wHandle, WM_CAP_GET_SEQUENCE_SETUP, SizeOf(CAPTUREPARMS), Integer(Addr(captureSettings))));
end;

function TCapture.SetCaptureSettings(const captureSettings: CAPTUREPARMS): longbool;
begin
  result := LongBool(SendMessage(wHandle, WM_CAP_SET_SEQUENCE_SETUP, SizeOf(CAPTUREPARMS), Integer(Addr(captureSettings))));
end;

function VideoStreamCallback(hWnd:cardinal;vHeader:pVIDEOHDR):cardinal; stdcall;
var
  owner:TCapture;
begin
  owner := TCapture(GetProp(hwnd,'OwnerObject'));
  if assigned(owner.cbVideoStream) then
    owner.cbVideoStream(owner,vHeader);
end;

function FrameCallback(hWnd:cardinal; vHeader:pVIDEOHDR):cardinal; stdcall;
var
  owner:TCapture;
begin
  owner := TCapture(GetProp(hwnd, 'OwnerObject'));
  if assigned(owner.cbFrame) then
    owner.cbFrame(owner,vHeader);
end;

function CapControlCallback(hWnd, nState:cardinal):cardinal; stdcall;
var
  owner:TCapture;
begin
  owner := TCapture(GetProp(hWnd, 'OwnerObject'));
  if assigned(owner.cbCapCtrl) then
    result := cardinal(owner.cbCapCtrl(owner,nState))
  else
    result := $FFFFFFFF;
end;

function ErrorCallback(hWnd,nId:Cardinal; nDescription:PAnsiChar):cardinal; stdcall;
var
  owner:TCapture;
begin
  owner := TCapture(GetProp(hwnd,'OwnerObject'));
  if assigned(owner.cbError) then
    owner.cbError(owner, nId, nDescription) ;
end;

function StatusCallback(hWnd,nId:Cardinal; nDescription:PAnsiChar):cardinal; stdcall;
var
  owner:TCapture;
begin
  owner := TCapture(GetProp(hwnd,'OwnerObject'));
  if assigned(owner.cbStatus ) then
    owner.cbStatus(owner, nId, nDescription);
end;

procedure TCapture.SetSingleFrame(sFrame: longbool);
begin
  if sFrame then
  begin
    if SendMessage(wHandle, WM_CAP_SINGLE_FRAME_OPEN, 0, 0) = 0 then exit;
  end
  else
  begin
    if SendMessage(wHandle, WM_CAP_SINGLE_FRAME_CLOSE, 0, 0) = 0 then exit;
  end;
  wSingleFrm := sFrame;
end;

function TCapture.CaptureStartSingleFrame: longbool;
begin
  result := LongBool(SendMessage(wHandle, WM_CAP_SINGLE_FRAME, 0, 0));
end;

function TCapture.VideoBufferToClipboard: longbool;
begin
  result := LongBool(SendMessage(wHandle, WM_CAP_EDIT_COPY, 0, 0));
end;

function TCapture.FrameToBitmapFile(const fileName: string): longbool;
begin
   result := LongBool(SendMessage(wHandle,WM_CAP_FILE_SAVEDIBA,0,Integer(Pointer(fileName))));
end;

function TCapture.FrameToJpgFile(const fileName: string; const bmpName: string; jpgCompression: integer): longbool;
var
  tempBmp :TBitmap;
  jpgImage: TJpegImage;
begin
  try
    tempBmp := TBitmap.Create;
    tempBmp.SaveToFile(bmpName);
    if LongBool(SendMessage(wHandle,WM_CAP_FILE_SAVEDIBA,0,Integer(Pointer(bmpName)))) then
    begin
      jpgImage := TJpegImage.Create;
      tempBmp.LoadFromFile(bmpName);
      jpgImage.Assign(tempBmp);
      jpgImage.CompressionQuality := jpgCompression;
      jpgImage.SaveToFile(fileName);
      result := true;
    end
    else
      result := false;
  finally
    tempBmp.Free;
    jpgImage.Free;
  end;
end;

function TCapture.FrameStill: longbool;
begin
  result := LongBool(SendMessage(wHandle,WM_CAP_GRAB_FRAME,0,0));
  if result then
    wPrev := false;
end;

function TCapture.GetInit: longbool;
begin
  result := longbool(wHandle);
end;

end.
